use glium::glutin;
use glutin::ContextBuilder;
use glutin::event::{Event, WindowEvent};
use glutin::event_loop::{EventLoop, ControlFlow};
use glutin::window::WindowBuilder;

use glium::{Display};

use super::AppListener;
use crate::math::Vector2;
use std::cell::Cell;
use glium::backend::glutin::glutin::event::ElementState;

pub struct App<L: AppListener> {
    event_loop: Option<Cell<EventLoop<()>>>,
    display: Display,
    cursor_pos: Vector2,
    key_down: bool,
    listener: L,
}

impl<L> App<L> where L: AppListener {
    pub fn new() -> Self {
        let event_loop = EventLoop::new();
        let display = {
            let wb = WindowBuilder::new().with_title("cbbtxdy").with_inner_size(glutin::dpi::PhysicalSize { width: 800, height: 800 });
            let cb = ContextBuilder::new();

            Display::new(wb, cb, &event_loop).unwrap()
        };

        let listener = L::new(&display);

        Self {
            event_loop: Some(Cell::new(event_loop)),
            display,
            cursor_pos: Vector2::zero(),
            key_down: false,
            listener,
        }
    }

    pub fn get_cursor_position(&self) -> Vector2 {
        self.cursor_pos
    }

    pub fn get_key_down(&self) -> bool {
        self.key_down
    }

    pub fn run(mut self) where L: 'static {
        let (w, h) = self.display.get_framebuffer_dimensions();
        let scr_dim = Vector2(w as f32, h as f32);
        let event_loop = self.event_loop.take().unwrap().into_inner();
        event_loop.run(move |event, _, cf| {
            *cf = ControlFlow::Poll;

            match event {
                Event::WindowEvent { event: e, .. } => {
                    match e {
                        WindowEvent::CloseRequested => *cf = ControlFlow::Exit,
                        WindowEvent::Resized(size) => self.listener.resize(size.width as f32, size.height as f32),
                        WindowEvent::CursorMoved { position, .. } => {
                            self.cursor_pos.set(position.x as f32, position.y as f32);
                            self.cursor_pos.1 = scr_dim.1 - self.cursor_pos.1;
                            println!("Cursor: {}", self.cursor_pos);
                        }
                        WindowEvent::MouseInput { state, .. } => {
                            if state == ElementState::Pressed {
                                self.key_down = true;
                                println!("Mouse Button Down!")
                            } else {
                                self.key_down = false;
                            }
                        }
                        _ => ()
                    }
                }
                Event::MainEventsCleared => {
                    // draw
                    let mut frame = self.display.draw();
                    self.listener.update(&self, &mut frame);
                    frame.finish().unwrap();
                    
                }
                Event::RedrawEventsCleared => {

                }
                _ => ()
            }
        });
    }
}
